/*
 * QuestInfo.cpp
 *
 *  Created on: 2013. 8. 28.
 *      Author: jjaehuny
 */

#include "QuestInfo.h"
#include "Static.h"
#include "../User.h"

namespace ProjectZ { namespace NLogic {

QuestInfo::Quest::Quest()
{
	_user = NULL;
}

QuestInfo::Quest::~Quest() {
}

void
QuestInfo::Quest::Open (Data & data, User * pUser)
{
	_data = data;
	_user = pUser;
}

QuestInfo::Quest::Data &
QuestInfo::Quest::GetData()
{
	return _data;
}

bool
QuestInfo::Quest::InsertQuestInfo()
{
	::Database::Command::Auto clsAuto(::Database::GETCOMMANDPOOL());
	clsAuto->SetQueryType(::Database::Command::S_PROCEDURE);
	clsAuto->MakeQuery("call sp_insert_info_quest(%d, %d, %d, %d, %d)",
			_user->GetCharacterInfo().characterseq, _data._questID, _data._idx, _data._state, _data._achieve);
	STRESSLOG("[CHANNEL] INSERTQUESTINFO QUERY : %s", clsAuto->GetQueryString());
	if (false == ::Database::GETSESSION()->SyncExecute(_user->GetUserInfo().shard_Item_db_type, clsAuto))
	{
		return false;
	}

	if( clsAuto->GetErrorIdx() != 0 )
	{
		return false;
	}

	return true;
}

bool
QuestInfo::Quest::UpdateQuestData()
{
	::Database::Command::Auto clsAuto(::Database::GETCOMMANDPOOL());
	clsAuto->SetQueryType(::Database::Command::S_PROCEDURE);
	clsAuto->MakeQuery("call sp_update_info_quest_data(%d, %d, %d)", _user->GetCharacterInfo().characterseq, _data._questID, _data._achieve);
	if (false == ::Database::GETSESSION()->SyncExecute(_user->GetUserInfo().shard_Item_db_type, clsAuto))
	{
		return false;
	}

	if( clsAuto->GetErrorIdx() != 0 )
	{
		return false;
	}

	return true;
}

bool
QuestInfo::Quest::UpdateQuestState()
{
	::Database::Command::Auto clsAuto(::Database::GETCOMMANDPOOL());
	clsAuto->SetQueryType(::Database::Command::S_PROCEDURE);
	clsAuto->MakeQuery("call sp_update_info_quest_state(%d, %d, %d)", _user->GetCharacterInfo().characterseq, _data._questID, _data._state);
	STRESSLOG("UpdateQuestState QUERY : %s", clsAuto->GetQueryString());
	if (false == ::Database::GETSESSION()->SyncExecute(_user->GetUserInfo().shard_Item_db_type, clsAuto))
	{
		return false;
	}

	if( clsAuto->GetErrorIdx() != 0 )
	{
		return false;
	}

	return true;
}

//bool
//QuestInfo::Quest::DeleteQuestInfo()
//{
//	::Database::Command::Auto clsAuto(::Database::GETCOMMANDPOOL());
//	clsAuto->SetQueryType(::Database::Command::S_PROCEDURE);
//	clsAuto->MakeQuery("call sp_delete_info_quest(%d, %d)", _user->GetCharacterInfo().characterseq, _data._questID);
//	STRESSLOG("UpdateQuestState QUERY : %s", clsAuto->GetQueryString());
//	if (false == ::Database::GETSESSION()->SyncExecute(_user->GetUserInfo().shard_Item_db_type, clsAuto))
//		return false;
//
//	if( clsAuto->GetErrorIdx() != 0 )
//		return false;
//
//	return true;
//}




QuestInfo::QuestInfo(User * pUser) : _user(pUser)
{
}

QuestInfo::~QuestInfo() {
}

void
QuestInfo::Initialize()
{
	clsQuestTree.clear();
	clsQuestHistory.clear();
}

void
QuestInfo::Finalize()
{
	std::for_each(clsQuestTree.begin(), clsQuestTree.end(), [](QUESTTREE::value_type& v) {
		NLogic::Static::InstancePtr()->GETQUESTPOOL()->DEL( v.second );
	} );
	clsQuestTree.clear();
	clsQuestHistory.clear();
}

bool
QuestInfo::QuestHistoryLoadFromDatabase()
{
	::Database::Command::Auto clsAuto(::Database::GETCOMMANDPOOL());
	clsAuto->SetQueryType(::Database::Command::S_PROCEDURE);
	clsAuto->MakeQuery("call sp_select_info_quest_history(%d)", _user->GetCharacterInfo().characterseq);
	if (false == ::Database::GETSESSION()->SyncExecute(_user->GetUserInfo().shard_Item_db_type, clsAuto))
	{
		return false;
	}

	if( clsAuto->GetErrorIdx() != 0 )
	{
		return false;
	}

	if (0 == clsAuto->ResultRowCount())
	{
		return true;
	}

	while( clsAuto->Next() )
	{
		uint16_t questID = 0;
		clsAuto->GetRecord() >> questID;
		this->AddQuestHistory(questID);
	}

	return true;
}

bool
QuestInfo::QuestLoadFromDatabase()
{
	::Database::Command::Auto clsAuto(::Database::GETCOMMANDPOOL());
	clsAuto->SetQueryType(::Database::Command::S_PROCEDURE);
	clsAuto->MakeQuery("call sp_select_info_quest(%d)", _user->GetCharacterInfo().characterseq);
	if (false == ::Database::GETSESSION()->SyncExecute(_user->GetUserInfo().shard_Item_db_type, clsAuto))
	{
		return false;
	}

	if( clsAuto->GetErrorIdx() != 0 )
	{
		return false;
	}

	if (0 == clsAuto->ResultRowCount())
	{
		//DEBUGLOG("QuestInfo::QuestLoadFromDatabase() FAIL GID : %d", _user->GetUserInfo().userseq);
		return true;
	}

	while( clsAuto->Next() )
	{
		Quest * pQuest = Static::InstancePtr()->GETQUESTPOOL()->NEW();

		Quest::Data clsData;
		int state = 0;
		clsAuto->GetRecord() >> clsData._questID >> clsData._idx >> state >> clsData._achieve;
		clsData._state = state;

		pQuest->Open(clsData, _user);

		this->addQuestFromDatabase(pQuest);
	}

	return true;
}

/// Quest
bool
QuestInfo::AddQuest(Quest * pQuest)
{
	auto itr = clsQuestTree.find(pQuest->GetData()._questID);
	if (itr != clsQuestTree.end())
		return false;

	if (false == pQuest->InsertQuestInfo())
		return false;

	clsQuestTree[pQuest->GetData()._questID] = pQuest;

	return true;
}

bool
QuestInfo::RemoveQuest(uint16_t questID)
{
	auto itr = clsQuestTree.find(questID);
	if (itr == clsQuestTree.end())
		return false;

	NLogic::QuestInfo::Quest * pQuest = itr->second;

	if ( false == pQuest->UpdateQuestState())
		return false;

	this->AddQuestHistory(itr->first);

	clsQuestTree.erase(itr);
	NLogic::Static::InstancePtr()->GETQUESTPOOL()->DEL( pQuest );

	return true;
}

bool
QuestInfo::RemoveQuestOnlyTree(uint16_t questID)
{
	auto itr = clsQuestTree.find(questID);
	if (itr == clsQuestTree.end())
		return false;

	NLogic::QuestInfo::Quest * pQuest = itr->second;

	clsQuestTree.erase(itr);
	NLogic::Static::InstancePtr()->GETQUESTPOOL()->DEL( pQuest );

	return true;
}

QuestInfo::Quest *
QuestInfo::GetQuest(uint16_t questID)
{
	auto itr = clsQuestTree.find(questID);
	if (itr == clsQuestTree.end())
		return NULL;

	return itr->second;
}

bool
QuestInfo::AddQuestHistory(uint16_t questID)
{
	if (true == IsExistQuestHistory(questID))
		return false;

	clsQuestHistory.push_back(questID);
	return true;
}

bool
QuestInfo::IsExistQuestHistory(uint16_t questID)
{
	for (auto itr = clsQuestHistory.begin(); itr != clsQuestHistory.end(); ++itr)
	{
		if ( (* itr) == questID)
		{
			return true;
		}
	}

	return false;
}

void
QuestInfo::addQuestFromDatabase(Quest * pQuest)
{
	auto itr = clsQuestTree.find(pQuest->GetData()._questID);
	if (itr != clsQuestTree.end())
		return;

	clsQuestTree[pQuest->GetData()._questID] = pQuest;
}


} /*NLogic*/ } /* namespace ProjectZ */
